<template>
  <div class="select-auth">
    <div v-if="showExpendAll" class="expend-all-btn" style="position: absolute;z-index: 2;left: 250px;top:2px" @click="expandTree">
      {{ expandTreeAll ?'一键收起':'一键展开' }}
      <i v-if="!expandTreeAll" class="el-icon-arrow-down" />
      <i v-if="expandTreeAll" class="el-icon-arrow-up" />
    </div>
    <el-tree
      ref="tree"
      :data="data"
      :default-checked-keys="defaultAuthList"
      :props="defaultProps"
      :render-after-expand="false"
      show-checkbox
      node-key="id"
      @current-change="nodeExpendChange"
      @check="selectAuth">
      <span slot-scope="{ node, data }" :class="{'last-level-style': data.isLast}" >
        <div v-if="!data.isLast" class="custom-tree-node">
          <div class="label title">{{ node.label }}</div>
          <div class="expend-btn">
            {{ node.expanded ?'收起':'展开' }}
            <i v-if="!node.expanded" class="el-icon-arrow-down" />
            <i v-if="node.expanded" class="el-icon-arrow-up" />
          </div>
        </div>
        <div v-if="data.isLast" class="custom-tree-node custom-last">
          <template v-if="hasRouteAuth('auth:remark:edit')">
            <el-tooltip
              v-if="remarksObj[data.id]"
              :open-delay="800"
              placement="top">
              <div slot="content" class="remarks-container">
                <div class="remarks-title">
                  <span class="remarks-title-label">权限说明</span>
                  <i class="remarks-icon el-icon-edit-outline" @click="openEditRemark(remarksObj[data.id])"/>
                </div>
                <div v-if="remarksObj[data.id].remarks">{{ remarksObj[data.id].remarks }}</div>
                <div v-else>暂无备注说明</div>
              </div>
              <div class="label">{{ node.label }}</div>
            </el-tooltip>
            <div v-else class="label">{{ node.label }}</div>
          </template>
          <template v-else>
            <el-tooltip
              v-if="remarksObj[data.id] && remarksObj[data.id].remarks"
              :open-delay="800"
              placement="top">
              <div slot="content" class="remarks-container">
                <div>{{ remarksObj[data.id].remarks }}</div>
              </div>
              <div class="label">{{ node.label }}</div>
            </el-tooltip>
            <div v-else class="label">{{ node.label }}</div>
          </template>

        </div>
      </span>
    </el-tree>
    <EditRemark ref="editRemarkEef" @handelOk="editRemark" />
  </div>
</template>

<script>
// mengliManage
import { allAuth, resourcePageAuth } from './authData';
import EditRemark from './editRemark';
import { getAuthId, editAuthRemark } from '@/api/auth';
import { hasRouteAuth } from '@/utils/permission';
import ElMessage from '@/utils/message';
import { mapState } from 'vuex';
import '@/styles/extend.scss';

export default {
  components: { EditRemark },
  props: {
    active: {
      type: String,
      default: 'role'
    },
    treeId: {
      type: String,
      default: ''
    },
    showExpendAll: {
      type: Boolean,
      default: false
    },
    isDisabled: {
      type: Boolean,
      default: false
    },
    defaultAuth: {
      type: Array | String,
      default() {
        return [];
      }
    }
  },
  data() {
    const allAuthList = JSON.parse(JSON.stringify(allAuth));
    return {
      data: allAuthList,
      defaultProps: {
        children: 'children',
        label: 'label',
        disabled: (data, node) => {
          if (this.isDisabled) return this.isDisabled;
          // 个别权限展示保留，但设置不可选，以备后续需要
          if (data.disabled) {
            return true;
          }
          const authList = this.jsonParse(this.userInfo.authList);
          // 拥有全向编辑或者是管理员，则全部可选
          const isAdmin = this.userInfo.userName === '管理员';
          if (authList.includes('auth:operator:adminEdit') || isAdmin) {
            return false;
          }
          if (!data.isLast && data.allChildrenList) {
            const hasAuth = data.allChildrenList.some(i => {
              return authList.includes(i);
            });
            return !hasAuth;
          }
          // 自己没有的权限无法选择
          if (data.id && data.id.indexOf('customAddId') < 0 && !authList.includes(data.id)) {
            return true;
          }
          return false;
        }
      },
      defaultAuthList: [],
      authIdList: [],
      selectAuthList: [],
      expandTreeAll: false,
      idsList: [],
      mediumAllAuth: null,
      remarksObj: {}
    };
  },
  computed: {
    ...mapState({
      'userInfo': state => state.user.userInfo
    })
  },
  created() {
    this.getList();
    this.setId(this.data);
    // console.log(this.data);
  },
  mounted() {
    this.$nextTick(() => {
      this.changeCss();
    });
  },
  methods: {
    hasRouteAuth,
    setDefault(defaultAuth) {
      try {
        this.defaultAuthList = defaultAuth ? this.jsonParse(defaultAuth) : [];
        this.sendAuth(this.defaultAuthList);
      } catch (error) {
        console.log(error);
      }
    },
    async getList() {
      try {
        const res = await getAuthId();
        this.authIdList = res.data;
        const remarksObj = {};
        res.data.forEach(i => {
          // if (i.remarks) {
          remarksObj[i.authUrl] = {
            remarks: i.remarks || '',
            id: i.id
          };
          // }
        });
        this.remarksObj = remarksObj;
        this.sendAuth(this.defaultAuthList);
      } catch (error) {
        console.log(error);
      }
    },
    selectAuth(data, checkList) {
      const authUrlArr = data.id ? data.id.split(':') : [];
      /** 点击其他权限时，自动联动可读权限 */
      const authHead = `${authUrlArr[0]}:${authUrlArr[1]}:`;
      // const authFooter = authUrlArr[2];
      const linkReadFooter = data.linkReadFooter || 'read';
      const readAuth = data.readAuth || [`${authHead}${linkReadFooter}`];
      let isSameLevel = false; // 所关联的可读权限必须与当前选中的权限同一层级，否则不进行关联
      if (data.isLast && data.brotherAuth) {
        isSameLevel = readAuth.every(item => {
          return data.brotherAuth.includes(item);
        });
      }
      if (data.isLast && authUrlArr.length >= 3 && !data.noRead && isSameLevel) {
        if (!readAuth.includes(data.id)) {
          /* 三个判断条件：
          * 1.当前点击的是取消权限还是增加权限，增加权限时触发
          * 2.当前选中列表是否已经有可读权限
          */
          const temp = readAuth.every(item => {
            return checkList.checkedKeys.includes(item);
          });
          if (checkList.checkedKeys.includes(data.id) && !temp) {
            checkList.checkedKeys = checkList.checkedKeys.concat(readAuth);
            this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
          }
          // 有不可取消联动权限 && 当前操作为取消选择 && 已选择不可取消联动权限，则不可取消当前操作
          if (data.notCancelWithAuth) {
            const res = data.notCancelWithAuth.every(item => {
              return checkList.checkedKeys.includes(item);
            });
            if (!checkList.checkedKeys.includes(data.id) && res) {
              checkList.checkedKeys = checkList.checkedKeys.concat(data.id);
              this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
            }
          }
        } else if (!checkList.checkedKeys.includes(data.id)) {
          // 如果当前点击的就是可读权限，判断是否已经选中其他权限，
          // 如果有其他选中的权限则不能取消可读，没有则可以
          const brotherAuth = data.brotherAuth || [];
          const currentCheckList = checkList.checkedKeys.filter(i => {
            const isBrotherAuth = brotherAuth.length === 0 ? true : brotherAuth.includes(i);
            return isBrotherAuth;
          });
          if (currentCheckList.length > 0) {
            checkList.checkedKeys = checkList.checkedKeys.concat(readAuth);
            this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
          }
        }
      }
      // 没有关联可读权限 && 有不可取消联动权限 && 当前操作为取消选择 && 已选择不可取消联动权限，则不可取消当前操作
      if (data.noRead && data.notCancelWithAuth && !checkList.checkedKeys.includes(data.id)) {
        const res = data.notCancelWithAuth.every(item => {
          return checkList.checkedKeys.includes(item);
        });
        if (res) {
          checkList.checkedKeys = checkList.checkedKeys.concat(data.id);
          this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
        }
      }
      /** 点击其他权限时，自动联动可读权限 end */

      /** 处理媒介权限：个人中心里面的销售只能二选一 */
      if (data.extern === 'mediumControlParent' || data.extern === 'mediumControlChildren') {
        this.handelMediumAuth(data, checkList);
      }
      if ((data.label === '销售' || data.label === '执行') && (!data.id || data.id.indexOf('customAddId') >= 0)) {
        this.mediumLabelAuth(data, checkList);
      }
      if (data.isLast && (data.id.indexOf('medium:sale:') >= 0 || data.id.indexOf('medium:medium:') >= 0)) {
        this.mediumLastAuth(data, checkList);
      }
      /** 处理媒介权限：个人中心里面的销售只能二选一 end */

      // 发送权限
      this.sendAuth(checkList.checkedKeys);
    },
    // 处理媒介权限：个人中心里面的销售只能二选一
    mediumLabelAuth(data, checkList) {
      const sales = 'medium:sale:';
      const medium = 'medium:medium:';
      const hasSalesAuth = checkList.checkedKeys.some(i => i && i.indexOf(sales) >= 0);
      const hasMediumAuth = checkList.checkedKeys.some(i => i && i.indexOf(medium) >= 0);
      const clickSales = data.label === '销售' && hasMediumAuth;
      const clickMedium = data.label === '执行' && hasSalesAuth;
      if (clickSales) {
        checkList.checkedKeys = checkList.checkedKeys.filter(i => {
          if (i) {
            return i.indexOf(sales) < 0 && i.indexOf('customAddId') < 0;
          }
          return true;
        });
        console.log('当前点击：销售，已存在媒介的权限，不能选中');
        ElMessage.warning('资源管理：销售与执行的订单展示权限只能二选一！');
        this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
      } else if (clickMedium) {
        checkList.checkedKeys = checkList.checkedKeys = checkList.checkedKeys.filter(i => {
          if (i) {
            return i.indexOf(medium) < 0 && i.indexOf('customAddId') < 0;
          }
          return true;
        });
        console.log('当前点击：执行，已存在销售的权限，不能选中');
        ElMessage.warning('资源管理：销售与执行的订单展示权限只能二选一！');
        this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
      }
    },
    // 处理媒介权限：个人中心里面的销售只能二选一
    mediumLastAuth(data, checkList) {
      const sales = 'medium:sale:';
      const medium = 'medium:medium:';
      const hasSalesAuth = checkList.checkedKeys.some(i => i && i.indexOf(sales) >= 0);
      const hasMediumAuth = checkList.checkedKeys.some(i => i && i.indexOf(medium) >= 0);
      const clickSales = data.id.indexOf(sales) >= 0 && hasMediumAuth;
      const clickMedium = data.id.indexOf(medium) >= 0 && hasSalesAuth;
      // 销售与媒介的订单展示权限只能二选一
      if (clickSales || clickMedium) {
        ElMessage.warning('资源管理：销售与执行的订单展示权限只能二选一！');
        // this.$message({
        //   type: 'warning',
        //   message: '媒介管理：销售与媒介的订单展示权限只能二选一！'
        // });
        // 移除当前选中的项目
        checkList.checkedKeys = checkList.checkedKeys.filter(i => i !== data.id);
        this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
      }
    },
    // 处理媒介权限：个人中心里面的销售只能二选一
    handelMediumAuth(data, checkList) {
      const sales = 'medium:sale:';
      const medium = 'medium:medium:';
      const checkedKeys = checkList.checkedKeys;
      const selectAuthList = this.selectAuthList;
      const mediumSaleAuth = ['medium:sale:orderList', 'medium:sale:statistics'];
      let mediumAllAuth = this.mediumAllAuth ? this.mediumAllAuth : this.getAllMeidum();
      const isSaleCheck = mediumSaleAuth.every(i => selectAuthList.includes(i)); // 销售所有权限都被选中

      const userAuthList = this.jsonParse(this.userInfo.authList);
      const hasMediumDisabled = userAuthList.some(i => { // 是否拥有媒介权限,true: 拥有媒介权限，可以自由选择  false: 没有：无法改变值
        return i.indexOf(medium) >= 0;
      });
      const hasSaleDisabled = userAuthList.some(i => { // 是否拥有销售权限
        return i.indexOf(sales) >= 0;
      });
      if (!isSaleCheck) {
        const hasSalesAuth = checkedKeys.some(i => i && i.indexOf(sales) >= 0);
        const hasMediumAuth = checkedKeys.some(i => i && i.indexOf(medium) >= 0);

        if (!hasMediumDisabled && hasSalesAuth && hasMediumAuth) {
          // 如果没有媒介权限，那么媒介权限无法变动
          // 所以如果这时候已经存在了媒介权限，那么销售无法被选中，需要被排除
          checkList.checkedKeys = checkedKeys.filter(i => {
            if (i) {
              return i.indexOf(sales) < 0 && i.indexOf('customAddId') < 0;
            }
            return true;
          });
          this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
        } else if (hasSalesAuth && hasMediumAuth) {
          checkList.checkedKeys = checkedKeys.filter(i => {
            if (i) {
              return i.indexOf(medium) < 0 && i.indexOf('customAddId') < 0;
            }
            return true;
          });
          this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
        }
      } else if (data.extern === 'mediumControlParent') {
        if (!hasSaleDisabled) {
          // 如果没有销售权限，那么无法改变销售的值，所以这里把销售的权限排除
          const salesList = ['medium:sale:orderList', 'medium:sale:statistics'];
          mediumAllAuth = mediumAllAuth.filter(i => {
            return !salesList.includes(i);
          });
        }
        checkList.checkedKeys = checkedKeys.filter(i => {
          if (i) {
            return !mediumAllAuth.includes(i) && i.indexOf('customAddId') < 0;
          }
          return true;
        });
        this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
      } else if (data.extern === 'mediumControlChildren') {
        let mediumAndSale = ['medium:sale:orderList', 'medium:sale:statistics', 'medium:medium:orderList', 'medium:medium:allShow'];
        if (!hasSaleDisabled) {
          // 如果没有销售权限，那么无法改变销售的值，所以这里把销售的权限排除
          mediumAndSale = ['medium:medium:orderList', 'medium:medium:allShow'];
        }
        checkList.checkedKeys = checkedKeys.filter(i => {
          if (i) {
            return !mediumAndSale.includes(i) && i.indexOf('customAddId') < 0;
          }
          return true;
        });
        this.$refs.tree.setCheckedKeys(checkList.checkedKeys);
      }
    },
    getAllMeidum() {
      const mediumAllAuth = [];
      const fun = function(authList) {
        if (authList.isLast) {
          mediumAllAuth.push(authList.id);
        } else if (authList.children) {
          authList.children.forEach(i => {
            fun(i);
          });
        }
      };
      fun(JSON.parse(JSON.stringify(resourcePageAuth)));
      this.mediumAllAuth = mediumAllAuth;
      return mediumAllAuth;
    },
    sendAuth(checkList) {
      const checkedKeys = checkList.filter(item => !!item);
      this.selectAuthList = checkedKeys;
      const result = this.authWordToId(checkedKeys);
      this.$emit('changeAuth', { authDataID: result, authDataWord: this.selectAuthList });
    },
    changeCss() {
      var levelName = document.getElementsByClassName('last-level-style'); // levelname是上面的最底层节点的名字
      for (var i = 0; i < levelName.length; i++) {
        levelName[i].parentElement.parentElement.style.cssFloat = 'left';
        levelName[i].parentElement.parentElement.style.styleFloat = 'left';
      }
    },
    setId(data, allChildrenList, parent) {
      data.forEach((i, index) => {
        if (!i.id) {
          i.id = (parent || '') + i.label + 'customAddId' + index + (i.idFoot || '');
          this.idsList.push(i.id);
          i.allChildrenList = this.getChildrenID(i.children, i.allChildrenList);
        }
        if (allChildrenList && i.isLast) {
          i.brotherAuth = allChildrenList;
        }
        if (i.children && i.children.length > 0) this.setId(i.children, i.allChildrenList, i.label);
      });
    },
    getChildrenID(node, list = []) {
      if (node) {
        for (let i = 0; i < node.length; i++) {
          if (node[i].isLast) {
            list.push(node[i].id);
          }
          if (node[i].children && node[i].children.length > 0) {
            this.getChildrenID(node[i].children, list);
          }
        }
      }
      return list;
    },
    authIdToWord(authIds) {
      const authIdList = this.authIdList;
      const result = authIdList.map(item => {
        if (authIds.includes(item.id)) {
          return item.authUrl;
        }
      }).filter(i => { return !!i; });
      return result;
    },
    authWordToId(authData) {
      const authIdList = this.authIdList;
      if (authData.length > 0) {
        const result = authIdList.map(item => {
          if (authData.includes(item.authUrl)) {
            return item.id;
          }
        }).filter(i => { return !!i; });
        return result;
      }
      return [];
    },
    jsonParse(data) {
      if (!data) return [];
      try {
        return typeof data === 'string' ? JSON.parse(data) : data;
      } catch (error) {
        return data;
      }
    },
    expandTree(emit = true) {
      if (!this.$refs.tree || !this.$refs.tree.store) return;
      const treeList = this.$refs.tree.store.nodesMap;
      this.expandTreeAll = !this.expandTreeAll;
      for (let i = 0; i < this.idsList.length; i++) {
        treeList[this.idsList[i]].expanded = this.expandTreeAll;
      }
      if (emit) {
        this.$nextTick(() => {
          this.$emit('nodeExpendChange', { type: 'all', treeId: this.treeId });
        });
      }
    },
    expandTreeItem({ key, expanded }) {
      if (!this.$refs.tree || !this.$refs.tree.store) return;
      const treeList = this.$refs.tree.store.nodesMap;
      treeList[key].expanded = expanded;
    },
    nodeExpendChange(data, node) {
      this.$nextTick(() => {
        this.$emit('nodeExpendChange', { key: data.id, expanded: node.expanded, type: 'node', treeId: this.treeId });
      });
    },
    setCheckAuth(list) {
      this.$refs.tree.setCheckedKeys(list);
    },
    openEditRemark(item) {
      this.$refs.editRemarkEef.openDialog(item);
    },
    editRemark(data, remarks) {
      const params = JSON.parse(JSON.stringify(data));
      params.remarks = remarks;
      editAuthRemark(params).then(res => {
        if (res.code === 200) {
          data.remarks = remarks;
          ElMessage.success('编辑成功');
        } else {
          ElMessage.error(res.message);
        }
      });
    }
  }
};
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.select-auth {
  padding-right: 10px;
  position: relative;
  &::v-deep {
    .el-checkbox {
      margin-right: 10px;
    }
    .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
      background-color: rgba(64, 110, 255, 0.5);
      border-color: rgba(64, 110, 255, 0.3);
      &:after {
        border-color: #fff;
      }
    }
    .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner {
      background-color: rgba(64, 110, 255, 0.5);
      border-color: rgba(64, 110, 255, 0.3);
      &::before {
        border-color: #fff;
        background-color: #fff;
      }
    }
    .el-tree-node__content {
      margin-bottom: 20px;
      background-color: #fff;
    }
    .el-tree-node__children {
      &:after{
        content: "";
        display: block;
        height: 0;
        clear:both;
        visibility: hidden;
      }
    }
    .el-tree-node__expand-icon{
      display: none;
    }
    .el-tree-node__content:hover {
      background-color: #fff;
    }

  }
  .custom-tree-node {
    display: flex;
    align-items: center;
    .title {
      font-weight:500;
    }
    .label {
      font-size: 14px;
    }
  }

  .expend-btn {
    margin-left: 10px;
    width:64px;
    height:22px;
    background:rgba(255,255,255,1);
    border-radius:4px;
    line-height: 21px;
    text-align: center;
    border:1px solid #406EFF;
    font-size:13px;
    font-family:AlibabaPuHuiTi-Regular,AlibabaPuHuiTi;
    color:#406EFF;
  }
  .expend-all-btn {
    margin-left: 10px;
    width:80px;
    height:22px;
    background:rgba(255,255,255,1);
    border-radius:4px;
    line-height: 21px;
    text-align: center;
    border:1px solid #999;
    font-size:13px;
    font-family:AlibabaPuHuiTi-Regular,AlibabaPuHuiTi;
    color:#333;
    cursor: pointer;
  }
}
.remarks-container {
  max-width: 300px;
  .remarks-title {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
    .remarks-title-label {
      flex:1;
      font-size: 14px;
      color: #406EFF;
    }
    .remarks-icon {
      cursor: pointer;
      font-size: 14px;
      margin-left: 20px;
      color: #406EFF;
    }
  }
}
</style>
